# -*- coding: utf-8 -*-
# 用来生成热更新需要用的flist文件
import os
import re
import shutil
import codecs
import ConfigParser
import hashlib
import sys
import zipfile
import zlib
from xml.dom import minidom
from optparse import OptionParser

class createFlist(object):
    
    def __init__(self):
        self.__source_path = ""                     #源路径 -- 默认为工作目录下,也可以用-p指定路径,会对指定路径下的res和src进行检索并获取md5
        self.__version = ""                         #设定资源版本号, 缺省值,如果不传入,则不修改版本号, 如果要改变版本号,使用-v来输入
        self.__core = ""                            #设定APP版本号, 缺省值,如果不传入,则不修改版本号, 如果要改变版本号,使用-c来输入
        self.__isZip = False                        #是否只对flist文件进行压缩
        self.__python_path = os.path.abspath('.')   #当前路径
        self.__path_list = []                       #路径字段数组
        self.__file_list = []                       #文件名数组
    
    def __check_arguments(self):
        '''检查参数
        '''
        
        parser = OptionParser()
        parser.add_option("-p", action="store", type="string", dest="project", help="project path")
        parser.add_option("-v", action="store", type ="string", dest="version", help="version path")
        parser.add_option("-c", action="store", type ="string", dest="core", help="core path")
        parser.add_option("-z", action="store", type ="string", dest="zip", help="iszip") #这个指令是用作只对flist文件进行压缩
        (options, args) = parser.parse_args()
        
        self.__option = options
        
        ok = True
        #更新文件路径和参数
        if ok:
            # sub, name1 = os.path.split(options.project)
            # sub, name2 = os.path.split(sub)
            
            self.__source_path = "./src/main/assets"
            # if options.project == None:
            #     self.__source_path = os.path.join(self.__python_path, os.pardir, os.pardir)

            # self.__source_config_path = os.path.join(self.__source_android_path, "config", options.channel + ".config")
            
            self.__temp_path = os.path.join(self.__python_path, "temp")

            import time

            year = time.strftime("%Y", time.localtime()) 
            # print year
            month = time.strftime("%m%d", time.localtime())
            # print month 
            tt = time.strftime("%H%M", time.localtime())
            # print tt 
            ss = year + "." + month + "." + tt 
            # print ss

            self.__version = ss
            # if options.version == None:
            #     #如果没有输入version的参数,则不修改版本号
            #     self.__key_path = ""

            self.__core = "1.0.0"
            # if options.core == None:
            #     #如果没有输入core的参数,则不修改APP版本号
            #     self.__core = ""
            if options.zip == None:
                #如果没有输入zip参数,则执行全部流程,否则只执行压缩
                self.__isZip = False
            else:
                self.__isZip = True

        print("self.__python_path == " + self.__python_path)
        print("self.__source_path == " + self.__source_path)
        
        return ok
    def __replace_text_by_file(self, path, old, new):
        '''替换文本文件中的文本
        '''
        print("path == " + path)
        # cur_file = codecs.open(path, "w", "utf-8")
        cur_file = file(path,'rb')
        b = cur_file.read()
        cur_file.close()

        cur_file = file(path,'wb')
        # print("temp_path",temp_path)
        # print("temp_file",temp_file)
        # print("cur_file",cur_file)
        pattern = old
        # for line in cur_file.readlines():
        params = pattern.findall(b)
        for item in params:
            old = item
            cur_file.write(b.replace(old, new))
        cur_file.close()

    def zip_dir(self, dirname, zipfilename):
        '''压缩一个文件或文件夹
        '''
        filelist = []
        #Check input ...
        # fulldirname = os.path.abspath(dirname)
        # fullzipfilename = os.path.abspath(zipfilename)
        print "Start to zip %s to %s ..." % (dirname, zipfilename)
        if not os.path.exists(dirname):
            print "Dir/File %s is not exist, Press any key to quit..." % dirname
            inputStr = raw_input()
            return
        if os.path.exists(zipfilename):
            os.remove(zipfilename)
      
        #Get file(s) to zip ...  
        if os.path.isfile(dirname):
            filelist.append(dirname)
            dirname = os.path.dirname(dirname)
        else:
            #get all file in directory
            for root, dirlist, files in os.walk(dirname):
                for filename in files:
                    filelist.append(os.path.join(root,filename))
      
        #Start to zip file ...
        destZip = zipfile.ZipFile(zipfilename, "w", zipfile.ZIP_DEFLATED)
        for eachfile in filelist:
            destfile = eachfile[len(dirname):]
            print "Zip file %s..." % destfile
            destZip.write(eachfile, destfile)
        destZip.close()
        print "Zip folder succeed!"

    def zip_str(self, fileStr, zipfilename):
        '''压缩一个字符串
        '''
        # #Check input ...
        # # fulldirname = os.path.abspath(dirname)
        # # fullzipfilename = os.path.abspath(zipfilename)
        # # print "Start to zip %s to %s ..." % (dirname, zipfilename)
        # if os.path.exists(zipfilename):
        #     os.remove(zipfilename)
      
        # #Start to zip file ...
        # destZip = zipfile.ZipFile(zipfilename, "w", zipfile.ZIP_DEFLATED)
        # destZip.writestr("flist", fileStr)
        # destZip.close()
        # print "Zip folder succeed!"

        # zipStr = zlib.compress(fileStr)
        # if os.path.exists(zipfilename):
        #     os.remove(zipfilename)
        # f=open(zipfilename,'a')
        # f.write(zipStr)
        # f.close()

        if os.path.exists(zipfilename):
            os.remove(zipfilename)
        infile = open(fileStr, 'rb')
        dst = open(zipfilename, 'wb')
        compress = zlib.compressobj(9)
        data = infile.read(1024)
        while data:
            dst.write(compress.compress(data))
            data = infile.read(1024)
        dst.write(compress.flush())
        infile.close()
        dst.close()

    def rezip_str(self, zipfilename):
        '''解压一个字符串
        '''
        # #Check input ...
        # # fulldirname = os.path.abspath(dirname)
        # # fullzipfilename = os.path.abspath(zipfilename)
        # # print "Start to zip %s to %s ..." % (dirname, zipfilename)
        # if os.path.exists(zipfilename):
        #     os.remove(zipfilename)
      
        # #Start to zip file ...
        # destZip = zipfile.ZipFile(zipfilename, "w", zipfile.ZIP_DEFLATED)
        # destZip.writestr("flist", fileStr)
        # destZip.close()
        # print "Zip folder succeed!"
        # f = file(zipfilename,'rb')
        # temp = ""
        # while True:
        #     b = f.read(8096)
        #     if not b :
        #         break
        #     temp += b
        # f.close()
        # cur_file = file(zipfilename,'rb')
        # temp = cur_file.read()
        # cur_file.close()
        # print("temp = " + temp)
        # zipStr = zlib.decompress(temp)
        # print("zipStr = " + zipStr)

        infile = open(zipfilename, 'rb')
        # dst = open(dst, 'wb')
        decompress = zlib.decompressobj()
        data = infile.read(1024)
        temp = ""
        while data:
            temp += decompress.decompress(data)
            data = infile.read(1024)
        temp += decompress.flush()
        # print("temp == "+ temp)

    def __get_md5_value(self, src):
        '''获取一个文件的md5值
        '''
        # myMd5 = hashlib.md5()

        # myMd5.update(src)

        # myMd5_Digest = myMd5.hexdigest()

        myhash = hashlib.md5()
        f = file(src,'rb')
        while True:
            b = f.read(8096)
            if not b :
                break
            myhash.update(b)
        f.close()
        return myhash.hexdigest()

    def __copy_dir(self, path, dest):
        '''复制一个文件夹,可覆盖
        '''
        #创建目录
        if not os.path.exists(dest):
            os.makedirs(dest)

        items = os.listdir(path)
        for item in items:
            # print("item",item)
            if item.find(".") != 0:
                #避开系统文件
                src = os.path.join(path, item)
                dst = os.path.join(dest, item)
                if os.path.isfile(src):
                    if os.path.exists(dst):
                        os.remove(dst)
                    shutil.copyfile(src, dst)
                else:
                    #否则如果是个文件夹,递归执行复制函数
                    self.__copy_dir(src,dst)

    def __make_flist(self):
        '''生成flist文件
        '''
        res = os.path.join(self.__source_path, "res")
        src = os.path.join(self.__source_path, "src")
        flist = os.path.join(self.__source_path, "res", "flist.txt")

        if self.__version != "":
            # 如果有输入版本号,则修改
            oldVersion = re.compile(r'version="(.*)"')
            newVersion = self.__version
            self.__replace_text_by_file(os.path.join(res, "version.txt"), oldVersion, newVersion)

        if self.__core != "":
            # 如果有输入版本号,则修改
            oldVersion = re.compile(r'core="(.*)"')
            newVersion = self.__core
            self.__replace_text_by_file(os.path.join(res, "version.txt"), oldVersion, newVersion)

        if self.__isZip == False:
            self.__findindir(res)
            self.__findindir(src)
            pthlen = len(self.__source_path) + 1

            print("ready to write")
            buf = "local flist = {\n"
            buf = buf + "\tdirs = {\n"
            for item in self.__path_list:
                fn = item[pthlen:]
                fn = fn.replace('\\','/')
                buf = buf+"\t\t{name = \""+fn+"\"},\n"

            print("write path finished!")
            buf = buf+"\t},\n" 
            buf = buf+"\tfiles = {\n" 
            print("start write file = " + buf)
            for item in self.__file_list:
                temp = item.split(';')
                fn = temp[0][pthlen:]
                fn = fn.replace('\\','/')
                size = temp[1]
                buf = buf + "\t\t{ file=\"" + fn + "\", md5=\""
                # file_object = open(temp[0])
                # try:
                #     all_the_text = file_object.read( )
                # finally:
                #     file_object.close()
                md5 = self.__get_md5_value(temp[0])
                # android版本需要给游戏资源md5+1
                # if item.find("GameRes") >= 0:
                #     md5 = md5 + "1"
                buf = buf + md5 + "\", size=\""+ size +"\"},\n" 

            buf = buf + "\t}\n"
            buf = buf + "}\n\n" 
            buf = buf + "return flist"

            if os.path.exists(flist):
                os.remove(flist)
            f=open(flist,'a')
            f.write(buf)
            f.close()

        print("write finished!!!")
        zipFile = os.path.join(self.__source_path, "res", "flist.zip")
        self.zip_str(flist , zipFile)
        print("zip finished!!!")
        # self.rezip_str(zipFile)
        return True

    def __findindir(self, path):
        '''获取一个目录里的文件的路径和文件名
        '''
        # print("path === " + path )
        items = os.listdir(path)
        for item in items:
            # print("item",item)
            if item != "." and item != ".." and item != ".DS_Store" and item != "flist.txt" and item != "version.txt" and item != "flist.zip" and item != ".svn":
            # and file != "launcher.lua" and file != "UILauncher.lua"
            # 打旧包更新时,屏蔽db的压缩包
            # and file != "game.zip" then
            # 打新包的更新时,屏蔽db文件,只处理压缩包
            # and file ~= "Ani_bingshuangX.ExportJson"
            # and file != "game.db" and file != "game.bin"  
            #避开系统文件
            #     file_object = open(item)
            # 　　try:
            #     all_the_text = file_object.read( )
            # 　　finally:
            #     file_object.close()
            #     md5 = self.__get_md5_value(all_the_text)
                src = os.path.join(path, item)
                # print("search path is " + src + " !!!!")
                if os.path.isfile(src):
                    size = os.path.getsize(src)
                    size = bytes(size)
                    src = src + ";" + size
                    self.__file_list.append(src)
                else:
                    #否则如果是个文件夹,记录当前路径,并递归执行
                    self.__path_list.append(src)
                    self.__findindir(src)


    def start(self):
        '''主入口
        '''
        ok = self.__check_arguments()
        if ok:
            print("check arguments success!!!")
        else:
            print("check arguments fail!!!")
            return

        ok = self.__make_flist()
        if ok:
            print("make flist success!!!")
        else:
            print("make flist fail!!!")
            return
            
        # self.clean_temp()

def main():
    createFlist().start()
    
if __name__ == '__main__':
    main()